/*******************************************************************************
 * Copyright (c) 2007 TOPCASED. All rights reserved. This program
 * and the accompanying materials are made available under the terms of the
 * Eclipse Public License v1.0 which accompanies this distribution, and is
 * available at http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors: Topcased contributors and others - initial API and implementation
 *******************************************************************************/
/**
 * This is a fork of the UML2Java Plug-in developed by Topcased and released under
 * the Eclipse EPL License. http://www.eclipse.org/legal/epl-v10.html
 * In accordance with the license, I have forked the UML2Java plugin and have adapted
 * it to suit the needs of a UML2QoS instrumentation code generator for PHP.
 * 
 * @author Alexandru Burdusel
 */
package org.topcased.uml2qos.services;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.StringTokenizer;
import java.util.Vector;

import org.eclipse.emf.ecore.EAnnotation;
import org.eclipse.uml2.uml.Comment;
import org.eclipse.uml2.uml.NamedElement;
import org.eclipse.uml2.uml.OpaqueBehavior;
import org.topcased.uml2qos.GenQosOperation;
import org.topcased.uml2qos.utilities.Configuration;
import org.topcased.uml2qos.utilities.Log;


/**
 * Comment Services : methods for generating comments from the class diagram
 * @author Ariel RAMPHUL (Sopra Group - Toulouse)
 */
public class CommentServices {

    /**
     * Comment Item : class for saving data related to a comment
     */    

    private class CommentItem
    {
        
        private int id;
        private String classe;
        private String type;
        private String text;

        public CommentItem(String c, String t, String ty, int i)
        {
            classe = c;
            text = t;
            type = ty;
            id = i;
        }

    }

    /**
     * List that contains all comments that are on the UML diagram
     */       
    private static Vector<CommentItem> commentList = new Vector<CommentItem>();

    /**
     * Add a comment in the comment list named "commentList"
     * @param c is the comment
     */
    public void addComment(Comment c)
    {

        String ty;

        for (int i=0;i<c.getAnnotatedElements().size();i++)
        {
            NamedElement e = (NamedElement)c.getAnnotatedElements().get(i);
            ty =  c.getAnnotatedElements().get(i).eClass().getName();
            commentList.add(new CommentItem(e.getName(),StringServices.addStarsNewLines(c.getBody()),ty,GenQosOperation.getLaunchID()));
        }

        saveCommentToFile();

    }

    /**
     * Return the number of return to line of the string s
     * @param s is the string
     * @return an integer that represent the number of line in s
     */
    public int nbLine(String s)
    {
        int i = 0;

        if (s!=null)
        {
            for (int j=0;j<s.length();j++)
            {
                if (s.charAt(j) == '\n')
                {
                    i++;
                }
            }
        }

        return i;
    }

    /**
     * Save the comment list to a file
     */
    public void saveCommentToFile()
    {
        try 
        {
            BufferedWriter out = new BufferedWriter(new FileWriter("_tmp"));
            for(int i =0;i<commentList.size();i++)
            {
                out.write(commentList.get(i).classe + "___");
                out.write(commentList.get(i).type + "___");
                out.write(commentList.get(i).id + "___");
                out.write(nbLine(commentList.get(i).text) + "\n");
                out.write(commentList.get(i).text + "\n");
            }
            out.close();
        } 
        catch (IOException e)
        {
            Log.log("(WRITE) IO Error while writting !");
        }
    }

    /**
     * Load the comment list from a file
     */
    public void loadCommentFromFile()
    {

        StringTokenizer st;
        String s;
        String classe;
        String type;
        String id;
        String comment;
        String nbl;

        try
        {
            BufferedReader bfr = new BufferedReader(new FileReader("_tmp"));            
            commentList.clear();
            while((s = bfr.readLine()) != null)
            {
                st = new StringTokenizer(s, "___"); 

                comment = "";
                classe = st.nextToken();
                type = st.nextToken();
                id = st.nextToken(); 
                nbl = st.nextToken();
                for(int i=0;i<(Integer.parseInt(nbl)+1);i++)
                {
                    s = bfr.readLine();
                    comment = comment + s;
                }
                commentList.add(new CommentItem(classe,comment,type,Integer.parseInt(id)));

            }
        }
        catch (IOException e)
        {
        	//If we are here, it means that there are no comments in the diagram
        	//Log.log("(READ) IO Error while loading comment file !");
        }
    }

    /**
     * Return the the comment associated to the association named "c"
     * @param c is the association name
     * @return the comment associated to the association named "c"
     */
    public static String generateAssociationComment(String c)
    {   
        String res = StringServices.addTab(1) + "/**\n";

        for (int i=0;i<commentList.size();i++)
        { 
            if ((c.compareTo(commentList.get(i).classe) == 0)&&(commentList.get(i).type.compareTo("Association")==0)&&(GenQosOperation.getLaunchID()==commentList.get(i).id))
            {
                if (commentList.get(i).text.compareTo("\n") != 0)
                {
                    res = res + StringServices.addTab(1) + " * " + commentList.get(i).text + "\n";
                }
            }
        }

        if (res.compareTo(StringServices.addTab(1) + "/**\n") == 0)
        {
            res = "";
        }
        else
        {
            res = res + StringServices.addTab(1) + " */\n";
        }

        return res;
    }   

    /**
     * Search for all comments related to the class "c" and add it to the comment list named "commentList"
     * @param c is the class to be analysed
     */
    public String generateComment(org.eclipse.uml2.uml.Class c)
    {   
        StringBuffer res = new StringBuffer("\n/**\n");
        
        if (c instanceof OpaqueBehavior)
        {
            return "";
        }
        
        res.append( " * " + c.eClass().getName() + " " + c.getName() + "\n"); 
        
        if (Configuration.getBooleanValue("GenerateAuthor"))
        {
            res.append( " * @author " + Configuration.getStringValue("Author") + "\n"); 
        }

        for (int i=0;i<commentList.size();i++)
        {
            if ((c.getName().compareTo(commentList.get(i).classe) == 0)&&(commentList.get(i).type.compareTo(c.eClass().getName())==0)&&(GenQosOperation.getLaunchID()==commentList.get(i).id))
            {
                if (commentList.get(i).text.compareTo("\n") != 0)
                {
                    res.append(" * " + commentList.get(i).text + "\n");
                }
            }
        }

        res.append(" */");

        return res.toString();
    }
    
    public String generateComment(org.eclipse.uml2.uml.Enumeration c)
    {   
        StringBuffer res = new StringBuffer("\n/**\n");
        
        res.append( " * " + c.eClass().getName() + " " + c.getName() + "\n"); 
        
        if (Configuration.getBooleanValue("GenerateAuthor"))
        {
            res.append( " * @author " + Configuration.getStringValue("Author") + "\n"); 
        }

        for (int i=0;i<commentList.size();i++)
        {
            if ((c.getName().compareTo(commentList.get(i).classe) == 0)&&(commentList.get(i).type.compareTo(c.eClass().getName())==0)&&(GenQosOperation.getLaunchID()==commentList.get(i).id))
            {
                if (commentList.get(i).text.compareTo("\n") != 0)
                {
                    res.append(" * " + commentList.get(i).text + "\n");
                }
            }
        }

        res.append(" */");

        return res.toString();
    }
    
    public String generateComment(org.eclipse.uml2.uml.Interface c)
    {   
        StringBuffer res = new StringBuffer("\n/**\n");
        
        res.append( " * " + c.eClass().getName() + " " + c.getName() + "\n"); 
        
        if (Configuration.getBooleanValue("GenerateAuthor"))
        {
            res.append( " * @author " + Configuration.getStringValue("Author") + "\n"); 
        }

        for (int i=0;i<commentList.size();i++)
        {
            if ((c.getName().compareTo(commentList.get(i).classe) == 0)&&(commentList.get(i).type.compareTo(c.eClass().getName())==0)&&(GenQosOperation.getLaunchID()==commentList.get(i).id))
            {
                if (commentList.get(i).text.compareTo("\n") != 0)
                {
                    res.append(" * " + commentList.get(i).text + "\n");
                }
            }
        }

        res.append(" */");

        return res.toString();
    }
    
    /**
     * Search for all comments related to the class "c" and add it to the comment list named "commentList"
     * @param c is an UML element
     * @return the loaded header if the user has selected to generate the header
     */ 
    public static String generateHeader(org.eclipse.uml2.uml.Element c)
    {
        if (c instanceof OpaqueBehavior)
        {
            return "";
        }
        
        if (Configuration.getBooleanValue("GenerateHeader"))
        {
            return Configuration.getHeader() + "\n";
        }
        else
        { 
            return "";
        }
    }
    
    public static void clearComments(org.eclipse.uml2.uml.Classifier c)
    {
        commentList.clear();
    }
    
    public void addEAnnotation(EAnnotation c)
    {

        String ty;

        for (int i=0;i<c.getReferences().size();i++)
        {
            NamedElement e = (NamedElement)c.getReferences().get(i);
            ty =  c.getReferences().get(i).eClass().getName();    
            commentList.add(new CommentItem(e.getName(),StringServices.addStarsNewLines(c.getSource()),ty,GenQosOperation.getLaunchID()));
        }

        saveCommentToFile();

    }
    
    public static String generateComment(String name, String type, String parent)
    {      
	    StringBuffer res = new StringBuffer("");
	    
	    //TODO Add a new parameter to the CommentItem structure (add "owner" attribute) to reduce errors
	    
	    for (int i=0;i<commentList.size();i++)
	    {
	        if ((name.compareTo(commentList.get(i).classe) == 0)&&(commentList.get(i).type.compareTo(type)==0)&&(GenQosOperation.getLaunchID()==commentList.get(i).id))
	        {
	            if (commentList.get(i).text.compareTo("\n") != 0)
	            {
	                res.append(StringServices.addTab(1) + "//" + commentList.get(i).text + "\n");
	            }
	        }
	    }
	    return res.toString();
	}
    
    public String generateComment(org.eclipse.uml2.uml.Operation c)
    {   
        StringBuffer res = new StringBuffer("");

        for (int i=0;i<commentList.size();i++)
        {
            if ((c.getName().compareTo(commentList.get(i).classe) == 0)&&(commentList.get(i).type.compareTo(c.eClass().getName())==0)&&(GenQosOperation.getLaunchID()==commentList.get(i).id))
            {
                if (commentList.get(i).text.compareTo("\n") != 0)
                {
                    res.append("\n" + StringServices.addTab(1)+ " * Description : " + commentList.get(i).text);
                }
            }
        }

        return res.toString();
    }
    
    public String generateInterfaceMethodComment(org.eclipse.uml2.uml.Operation c)
    {   
        StringBuffer res = new StringBuffer("");

        for (int i=0;i<commentList.size();i++)
        {
            if ((c.getName().compareTo(commentList.get(i).classe) == 0)&&(commentList.get(i).type.compareTo(c.eClass().getName())==0)&&(GenQosOperation.getLaunchID()==commentList.get(i).id))
            {
                if (commentList.get(i).text.compareTo("\n") != 0)
                {
                    res.append("\n" + StringServices.addTab(1)+ "//Description : " + commentList.get(i).text);
                }
            }
        }

        return res.toString();
    }

}
